package com.handu.luna.core.domain.search;

import com.handu.luna.core.domain.BaseDomain;
import com.handu.luna.core.domain.goods.Goods;
import com.handu.luna.core.domain.goods.goodsMatch.GoodsMatch;
import com.handu.luna.core.domain.promotion.Activities;
import com.handu.luna.core.domain.promotion.PostForFreeActivity;
import com.handu.luna.core.domain.promotion.combo.Combo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created by zhq on 2014/8/11.
 * 统一商品查询
 * 可以进行属性的扩展（增加查询的条件） 相应的在searchabledGoods方法中改动添加搜索条件
 */
public class GoodsSearchCondition extends BaseDomain{


    private long searchId;

    private String categoryId;

    private String brandId;

    private String goodsName;

    private String goodSN;

    private String excludGoodsIds;


    public enum SearchType{
        MATCH,COMBO,TOPIC,ACTIVITIES,POSTFORFREEACTIVITY;
    }
//      暂不提供的功能
//    public enum CompareType{
//
//        EQUALS("equals"),IN("in"),LIKE("like");
//
//        private String description;
//        private CompareType(String description){
//            this.description = description;
//        }
//    }


    public GoodsSearchCondition(long searchId, SearchType searchType) {
        this.searchId = searchId;
        this.searchType = searchType;
    }

    public GoodsSearchCondition(SearchType searchType) {
        this.searchId = 0;
        this.searchType = searchType;
    }

    public GoodsSearchCondition() {super();}

    private SearchType searchType;

    public long getSearchId() {
        return searchId;
    }

    public void setSearchId(long searchId) {
        this.searchId = searchId;
    }

    public String getCategoryId() {
        return categoryId;
    }

    public void setCategoryId(String categoryId) {
        this.categoryId = categoryId;
    }

    public String getBrandId() {
        return brandId;
    }

    public void setBrandId(String brandId) {
        this.brandId = brandId;
    }

    public String getGoodsName() {
        return goodsName;
    }

    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    public String getGoodSN() {
        return goodSN;
    }

    public void setGoodSN(String goodSN) {
        this.goodSN = goodSN;
    }

    public SearchType getSearchType() {
        return searchType;
    }

    public void setSearchType(SearchType searchType) {
        this.searchType = searchType;
    }

    public String getExcludGoodsIds() {
        return excludGoodsIds;
    }

    public void setExcludGoodsIds(String excludGoodsIds) {
        this.excludGoodsIds = excludGoodsIds;
    }

    public Specification<Goods> searchabledGoods(GoodsSearchCondition searchCondition){
        return new Specification<Goods>() {
            @Override
            public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

                Predicate predicate = cb.conjunction();
                List<Expression<Boolean>> expressions = predicate.getExpressions();

                expressions.add(cb.equal(root.<Boolean> get("deleted"),false));
                expressions.add(cb.equal(root.<Boolean> get("displayed"),true));

                if (StringUtils.isNotBlank(searchCondition.getCategoryId())){
                    expressions.add(cb.equal(root.<Long>get("categoryId"),Long.parseLong(searchCondition.getCategoryId())));
                }
                if (StringUtils.isNotBlank(searchCondition.getBrandId())){
                    expressions.add(cb.equal(root.<Long>get("brandId"),Long.parseLong(searchCondition.getBrandId())));
                }
                if (StringUtils.isNotBlank(searchCondition.getGoodsName())){
                	expressions.add(cb.or(cb.like(root.<String>get("name"),"%"+searchCondition.getGoodsName()+"%"),cb.equal(root.<String>get("goodsSN"),  searchCondition.getGoodsName())));
                    //expressions.add(cb.like(root.<String>get("name"),"%"+searchCondition.getGoodsName()+"%"));
                }
                if (StringUtils.isNotBlank(searchCondition.getGoodSN())){
                  //  expressions.add(cb.equal(root.<String>get("goodsSN"), "%" + searchCondition.getGoodSN() + "%"));
                    expressions.add(cb.equal(root.<String>get("goodsSN"),  searchCondition.getGoodSN()));
                }

                Set<Long> excludGoodsIdSet = new HashSet<>();
                if (StringUtils.isNotBlank(searchCondition.getExcludGoodsIds())){
                    for(String matchedId:searchCondition.getExcludGoodsIds().split(",")){
                        excludGoodsIdSet.add(Long.parseLong(matchedId));
                    }
                }else{
                    switch (searchCondition.getSearchType().name()){
                        case "MATCH":
                            excludGoodsIdSet.add(searchCondition.getSearchId());
                            excludGoodsIdForMatch(excludGoodsIdSet,searchCondition.getSearchId());
                            break;
                        case "COMBO":
                            excludGoodsIdForCombo(excludGoodsIdSet,searchCondition.getSearchId());
                            break;
                        case "ACTIVITIES":
                            excludGoodsIdForActivities(excludGoodsIdSet,searchCondition.getSearchId());
                            break;
                        case "POSTFORFREEACTIVITY":
                            excludGoodsIdForPostForFree(excludGoodsIdSet,searchCondition.getSearchId());
                            break;
                        case "TOPIC":
                            // DO NOTHING
                            break;
                        //可以继续进行扩展 重写自己的获取排除商品ID的方法
                        default:
                            //DO SOMETHING
                            break;
                    }
                }
                if (CollectionUtils.isNotEmpty(excludGoodsIdSet)){
                    expressions.add(cb.not(root.<Long>get("id").in(excludGoodsIdSet)));
                }
                return query.where(predicate).getRestriction();
            }
        };
    }


    private void excludGoodsIdForMatch(Set<Long> excludGoodsIdSet,long id){
        List<GoodsMatch> list1 = context.getGoodsMatchRepository().findByPrimaryGoodsId(id);
        if(list1 != null && list1.size()>0){
            for(GoodsMatch match:list1){
                excludGoodsIdSet.add(match.getCascadGoodsId());
            }
        }
    }

    private void excludGoodsIdForCombo(Set<Long> excludGoodsIdSet,long id){
        Combo combo = context.getComboRepository().findOne(id);
        if (combo!=null){
            addIds(excludGoodsIdSet,combo.getComboGoodsIds());
        }
    }

    private void excludGoodsIdForActivities(Set<Long> excludGoodsIdSet,long id){
        Activities activities = context.getActivitiesRepository().findOne(id);
        if (activities!=null){
            addIds(excludGoodsIdSet,activities.getActivitiesGoodsids());
        }
    }

    private void excludGoodsIdForPostForFree(Set<Long> excludGoodsIdSet,long id){
        PostForFreeActivity activity = context.getPostForFreeActivityRepository().findOne(id);
        if (activity != null){
            addIds(excludGoodsIdSet,activity.getGoodsIdArr());
        }
    }

    private void addIds(Set<Long> excludGoodsIdSet,String ids){
        if (StringUtils.isNotBlank(ids)){
            for (String id:ids.split(",")){
                excludGoodsIdSet.add(Long.parseLong(id));
            }
        }
    }



}
